home *** CD-ROM | disk | FTP | other *** search
- /* _______________
- ** getstart, fatck - get starting cluster, FAT consistency check
- ** atari corp (1 March 1988) asm
- **
- ** see GETSTART(3) manual pages
- **
- ** Fatck and support algorithms are courtesy Derek Mui.
- **
- ** $Header$
- ** $Source$
- ** $Author$
- **
- ** $Revision$
- ** $Date$
- ** $State$
- ** $Locker$
- ** $Log$
- */
-
-
-
- # include <osbind.h>
- # include "getstart.h"
-
- # define OSIZE (32767) /* orphan list size in words */
- # define ROOT (0) /* root directory dummy cluster */
- # define EOFAT (0xffff) /* end of file allocation chain */
-
- BPB *bp; /* pointer to device BPB */
- char *fat1buf; /* first FAT buffer */
- char *fat2buf; /* second FAT buffer */
- char *rootbuf; /* root directory buffer */
- char *clusbuf; /* general-purpose cluster buffer */
-
-
-
- /*
- ** Get starting cluster.
- */
-
- GSINFO *getstart (orphans, clusno, devno)
- register int *orphans;
- register int clusno, devno;
- {
- static GSINFO info;
- register unsigned i, fatlen;
-
- if ((long)orphans <= 0L)
- return ((GSINFO *)GOOFY); /* FAT not validated by fatck */
-
- if (!allobuf (devno)) /* cache for FATs and root directory */
- {
- freebuf ();
- return (GFAIL);
- }
- if (!readfat (devno)) /* get first and second FATs */
- {
- freebuf ();
- return (GFAIL);
- }
- if (!readroo (devno)) /* get root directory */
- {
- freebuf ();
- return (GFAIL);
- }
-
- if (!nextcl (clusno))
- {
- freebuf ();
- return ((GSINFO *)GALLO); /* current cluster not allocated */
- }
- if (bsearch ((orphans+1), *orphans, clusno))
- {
- freebuf ();
- return ((GSINFO *)GORPH); /* orphan in FAT allocation chain */
- }
-
- info.gs_count = 1; /* backtrack file allocation chain */
- info.gs_prev = 0;
- fatlen = bp->numcl + 2;
- while (1) /* look up and down FAT */
- {
- for (i = clusno - 1; i >= 2; i--)
- if (nextcl (i) == clusno)
- {
- clusno = i;
- if (bsearch ((orphans+1), *orphans, clusno))
- {
- freebuf ();
- return ((GSINFO *)GORPH);
- }
- info.gs_count++;
- if (!info.gs_prev)
- info.gs_prev = clusno;
- }
- for (i = clusno + 1; i <= fatlen; i++)
- if (nextcl (i) == clusno)
- {
- clusno = i;
- if (bsearch ((orphans+1), *orphans, clusno))
- {
- freebuf ();
- return ((GSINFO *)GORPH);
- }
- info.gs_count++;
- if (!info.gs_prev)
- info.gs_prev = clusno;
- break;
- }
- if (i > fatlen)
- break;
- }
- info.gs_head = clusno;
-
- branch (devno, ROOT, clusno, &info); /* find starting cluster */
-
- freebuf ();
- return (&info);
- }
-
-
-
- /*
- ** FAT consistency check.
- */
-
- int *fatck (devno)
- register int devno;
- {
- static int olist[OSIZE];
- register unsigned i, fatlen;
-
- if (!allobuf (devno)) /* cache for FATs and root directory */
- {
- freebuf ();
- return (FFAIL);
- }
- if (!readfat (devno)) /* get first and second FATs */
- {
- freebuf ();
- return ((int *)FFATS);
- }
- if (!readroo (devno)) /* get root directory */
- {
- freebuf ();
- return ((int *)FROOT);
- }
-
- fatlen = bp->fsiz * bp->recsiz; /* compare first and second FATs */
- for (i = 0; i < fatlen; i += sizeof(long))
- if (*((long *)(fat1buf+i)) != *((long *)(fat2buf+i)))
- {
- freebuf ();
- return ((int *)FCONF); /* conflicting FAT entry */
- }
-
- fatlen = bp->numcl + 2; /* zero tallies */
- for (i = 2; i <= fatlen; i += sizeof(long))
- *((long *)(fat2buf+i)) = 0L;
-
- branch (devno, ROOT, 0, 0L); /* traverse entire directory tree */
-
- olist[0] = 0; /* check tallies, build orphan list */
- for (i = 2; i <= fatlen; i++)
- {
- if (*(fat2buf+i) > 1)
- {
- freebuf ();
- return ((int *)FAMBI); /* ambiguous FAT entry reference */
- }
- if (!(*(fat2buf+i)) && nextcl (i))
- olist[++olist[0]] = i;
- }
-
- freebuf ();
- return (&olist[0]);
- }
-
-
-
- /*
- ** Miscellaneous support functions.
- */
-
- int allobuf (dev) /* allocate memory for buffers */
- int dev;
- {
- if (!(bp = (BPB *)Getbpb (dev)))
- return (0);
- if (!(fat1buf = (char *)Malloc ((long)bp->fsiz * (long)bp->recsiz)))
- return (0);
- if (!(fat2buf = (char *)Malloc ((long)bp->fsiz * (long)bp->recsiz)))
- return (0);
- if (!(rootbuf = (char *)Malloc ((long)bp->rdlen * (long)bp->recsiz)))
- return (0);
- return ((int)(clusbuf = (char *)Malloc ((long)bp->clsiz
- * (long)bp->recsiz)));
- }
-
- int readfat (dev) /* read first and second FATs */
- int dev;
- {
- if (Rwabs (0, fat1buf, bp->fsiz, bp->fatrec - bp->fsiz, dev))
- return (0);
- return (!Rwabs (0, fat2buf, bp->fsiz, bp->fatrec, dev));
- }
-
- int readroo (dev) /* read root directory */
- int dev;
- {
- return (!Rwabs (0, rootbuf, bp->rdlen, bp->fatrec + bp->fsiz, dev));
- }
-
- int readclu (cl, dev) /* read cluster */
- int cl, dev;
- {
- return (!Rwabs (0, clusbuf, bp->clsiz, (cl-2)*bp->clsiz+bp->datrec, dev));
- }
-
- int freebuf () /* free memory for buffers */
- {
- Mfree (rootbuf);
- Mfree (fat1buf);
- Mfree (fat2buf);
- Mfree (clusbuf);
- }
-
- int branch (devo, clus, key, inf) /* recursive branch traverse */
- register int devo, clus, key;
- register GSINFO *inf;
- {
- register FCB *fp;
- register int fcount, fx;
- int sclus, nclus, px;
- if (clus != ROOT)
- {
- (*(fat2buf+clus))++;
- if (!readclu (clus, devo))
- {
- if (inf)
- inf->gs_fpath[0] = '\0';
- return (0);
- }
- fp = (FCB *)clusbuf;
- fcount = (bp->clsizb / sizeof(FCB)) - 1;
- }
- else
- {
- if (inf)
- inf->gs_fpath[px = 0] = '\0';
- fp = (FCB *)rootbuf;
- fcount = ((bp->rdlen * bp->recsiz) / sizeof(FCB)) - 1;
- }
- fx = 0;
- while (fx <= fcount)
- {
- if ((fp->f_name[0] != FN_FRE) && ((fp->f_name[0] & 0xff) != FN_DEL)
- && (fp->f_name[0] != FN_DIR) && fp->f_clust)
- {
- swapb (&fp->f_clust, &sclus);
- if (key == sclus)
- {
- inf->gs_dsect = ((clus != ROOT) ? (clus-2)*bp->clsiz+bp->datrec
- : (bp->fatrec + bp->fsiz) + (fx / (bp->recsiz / sizeof(FCB))));
- inf->gs_doff = (fx * sizeof(FCB)) % bp->recsiz;
- addfn (&fp->f_name[0], &inf->gs_fpath[0]);
- return (1);
- }
- if (fp->f_attrib == FA_SUB)
- {
- if (inf)
- px = addfn (&fp->f_name[0], &inf->gs_fpath[0]);
- if (branch (devo, sclus, key, inf))
- return (1);
- if (inf)
- inf->gs_fpath[px] = '\0';
- if (clus != ROOT)
- if (!readclu (clus, devo))
- {
- if (inf)
- inf->gs_fpath[0] = '\0';
- return (0);
- }
- }
- else if (!key)
- leaf (sclus);
- }
- if ((clus != ROOT) && (fx == fcount))
- {
- nclus = nextcl (clus);
- if (!nclus || (nclus == EOFAT))
- break;
- if (*(fat2buf+nclus))
- {
- (*(fat2buf+nclus))++;
- break;
- }
- clus = nclus;
- (*(fat2buf+clus))++;
- if (!readclu (clus, devo))
- {
- if (inf)
- inf->gs_fpath[0] = '\0';
- return (0);
- }
- fp = (FCB *)clusbuf, fx = 0;
- }
- else
- fp++, fx++;
- }
- return (0);
- }
-
- int leaf (clus) /* linear leaf traverse */
- register int clus;
- {
- register int nclus;
- (*(fat2buf+clus))++;
- nclus = nextcl (clus);
- while (nclus && (nclus != EOFAT))
- {
- if (*(fat2buf+nclus))
- {
- (*(fat2buf+nclus))++;
- break;
- }
- clus = nclus;
- (*(fat2buf+clus))++;
- nclus = nextcl (clus);
- }
- }
-
- int nextcl (cl) /* next cluster in chain */
- register int cl;
- {
- unsigned ncl;
- if (bp->b_flags & BF_F16)
- {
- swapb (fat1buf+(cl*2), &ncl);
- ncl = ((ncl >= 0xfff0) && (ncl <= 0xffff)) ? EOFAT : ncl;
- }
- else
- {
- swapb (fat1buf+(cl+(cl/2)), &ncl);
- if (cl & 0x0001)
- ncl >>= 4;
- ncl &= 0x0fff;
- ncl = ((ncl >= 0x0ff0) && (ncl <= 0x0fff)) ? EOFAT : ncl;
- }
- return (ncl);
- }
-
- int addfn (src, dst) /* add file name to path string */
- register char *src, *dst;
- {
- register int old, i;
- for (old = 0; *dst; dst++, old++);
- *dst++ = '\\';
- for (i = 0; i < 11; src++, i++)
- {
- if ((*src) && (*src != ' '))
- {
- if (i == 8)
- *dst++ = '.';
- *dst++ = *src;
- }
- }
- *dst = '\0';
- return (old);
- }
-
- int bsearch (list, len, key) /* binary search a la k&r */
- register int list[], len, key;
- {
- register int low, mid, high;
- low = 0;
- high = len - 1;
- while (low <= high)
- {
- mid = (low + high) / 2;
- if (key < list[mid])
- high = mid - 1;
- else if (key > list[mid])
- low = mid + 1;
- else
- return (1);
- }
- return (0);
- }
-
- int swapb (from, to) /* swap adjacent bytes */
- register char *from, *to;
- {
- register char temp;
- temp = *from++;
- *to++ = *from;
- *to = temp;
- }
-